package serv

import (
	"context"
	"generate_grom_mode_and_dao/common/helper"
	"generate_grom_mode_and_dao/service/genertategrom/api/internal/svc"
	"generate_grom_mode_and_dao/service/genertategrom/api/model"
	"github.com/tal-tech/go-zero/core/logx"
	"strings"
)

type DatabaseService interface {
	IsIdentity(c model.InformationSchemaColumns) bool
	IsPrimary(c model.InformationSchemaColumns) bool
	GoLangType(c model.InformationSchemaColumns) string
	JavaType(c model.InformationSchemaColumns) string
	IsDateType(c model.InformationSchemaColumns) bool
	IsDecimalType(c model.InformationSchemaColumns) bool
	IsDelStatus(c model.InformationSchemaColumns) bool
	Tag(c model.InformationSchemaColumns) string
}

type defaultDatabaseService struct {
	logx.Logger
	ctx    context.Context
	svcCtx *svc.ServiceContext
}

func NewDatabaseService(ctx context.Context, svcCtx *svc.ServiceContext) *defaultDatabaseService {
	return &defaultDatabaseService{
		Logger: logx.WithContext(ctx),
		ctx:    ctx,
		svcCtx: svcCtx,
	}
}
func (s *defaultDatabaseService) IsIdentity(c model.InformationSchemaColumns) bool {
	return strings.ToLower(c.Extra) == "auto_increment"
}
func (s *defaultDatabaseService) IsPrimary(c model.InformationSchemaColumns) bool {
	return strings.ToLower(c.ColumnKey) == "pri"
}
func (s *defaultDatabaseService) GoLangType(c model.InformationSchemaColumns) string {
	dataType := strings.ToLower(c.DataType)
	nullable := strings.ToLower(c.IsNullable) == "yes"
	if dataType == "int" {
		if nullable {
			return "*int"
		}
		return "int"
	}
	if dataType == "varchar" || dataType == "text" || dataType == "longtext" {
		if nullable {
			return "*string"
		}
		return "string"
	}
	if dataType == "long" || dataType == "bigint" {
		if nullable {
			return "*int64"
		}
		return "int64"
	}
	if dataType == "decimal" {
		if nullable {
			return "*float64"
		}
		return "ifloat64"
	}
	if dataType == "datetime" {
		if nullable {
			return "*core.LocalDateTime"
		}

		return "core.LocalDateTime"
	}
	return dataType
}

func (s *defaultDatabaseService) JavaType(c model.InformationSchemaColumns) string {
	dataType := strings.ToLower(c.DataType)
	if dataType == "int" {
		return "Integer"
	} else if dataType == "varchar" || dataType == "text" || dataType == "longtext" {
		return "String"
	} else if dataType == "long" || dataType == "bigint" {
		return "Long"
	} else if dataType == "decimal" {
		return "BigDecimal"
	} else if dataType == "datetime" {
		return "LocalDateTime"
	} else {
		return c.DataType
	}
}

func (s *defaultDatabaseService) IsDateType(c model.InformationSchemaColumns) bool {
	return strings.ToLower(c.DataType) == "datetime"
}

func (s *defaultDatabaseService) IsDecimalType(c model.InformationSchemaColumns) bool {
	return strings.ToLower(c.DataType) == "decimal"
}
func (s *defaultDatabaseService) IsDelStatus(c model.InformationSchemaColumns) bool {
	return c.ColumnName == "del_status"
}

func (s *defaultDatabaseService) Tag(c model.InformationSchemaColumns) string {
	name := strings.ToLower(c.ColumnName)
	dataType := strings.ToLower(c.DataType)
	identity := strings.ToLower(c.Extra) == "auto_increment"
	primary := strings.ToLower(c.ColumnKey) == "pri"
	nullable := strings.ToLower(c.IsNullable) == "yes"

	sb := new(strings.Builder)

	sb.WriteString("`xorm:\"")
	sb.WriteString(dataType)
	sb.WriteString(" '")
	sb.WriteString(name)
	sb.WriteString("'")

	if identity {
		sb.WriteString(" autoincr")
	}

	if primary {
		sb.WriteString(" pk")
	}

	if nullable {
		sb.WriteString(" null")
	} else {
		sb.WriteString(" notnull")
	}

	sb.WriteString(" default(")

	if dataType == "varchar" || dataType == "text" || dataType == "longtext" {
		sb.WriteString("'")
	}

	sb.WriteString(c.ColumnDefault)

	if dataType == "varchar" || dataType == "text" || dataType == "longtext" {
		sb.WriteString("'")
	}

	sb.WriteString(")")

	sb.WriteString(" comment('")
	sb.WriteString(c.ColumnComment)
	sb.WriteString("')")

	sb.WriteString("\" json:\"")

	if name == "del_status" {
		sb.WriteString("-")
	} else {
		sb.WriteString(helper.StringHelperObject.LowerCamelCase(c.ColumnName))
	}

	sb.WriteString("\"`")

	return sb.String()
}
